home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / tcp_ip / wnos / wn941101 / domserv.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-02  |  19.9 KB  |  821 lines

  1. /* Domain/Name server
  2.  * Copyright 1991/2 KA9Q, PA0GRI, DK5DC and DB3FL
  3.  *
  4.  * ported to WNOS from a previous PA0GRI issue by DB3FL
  5.  *
  6.  * some code streaming and fixing done - DB3FL.91xxxx/92xxxx
  7.  * added cache from DK5DC - DB3FL.92xxxx
  8.  * some fixes by WZ8Y - 9206xx
  9.  *
  10.  */
  11.  
  12. #include "global.h"
  13. #include "config.h"
  14. #include "socket.h"
  15. #include "domain.h"
  16. #include "files.h"
  17. #include "netuser.h"
  18. #include "iface.h"
  19.  
  20. #define RR_QUERY    8
  21. #define RR_INQUERY   9
  22.  
  23. static struct rr * near resolverec __ARGS((char *name,int type));
  24. static struct rr * near rresolve __ARGS((char *name,int type,int16 fflag));
  25. static int SDom = -1;
  26. Cache *cache;
  27.  
  28. static int near
  29. strxlen(char *s)
  30. {
  31.     int i = 0;
  32.  
  33.     while(*s++ != '\0')
  34.         i++;
  35.     return i;
  36. }
  37.  
  38. /* Resolve an arbitrary record */
  39. static struct rr * near
  40. resolverec(name,type)
  41. char *name;
  42. int type;
  43. {
  44.     struct rr *rrp;
  45.     char *pname = NULLCHAR, *cname = NULLCHAR;
  46.     FILE *dbase;
  47.     struct rr_memory *memory;
  48.  
  49.     if(name == NULLCHAR)
  50.         return NULLRR;
  51.  
  52.     if(DBloaded)
  53.         dbase = NULLFILE;
  54.     else
  55.         if((dbase = fopen(Dfile,READ_TEXT)) == NULLFILE)
  56.             return NULLRR;
  57.  
  58.     memory = (struct rr_memory *)mxallocw(sizeof(struct rr_memory));
  59.     memory->Dname[0] = '\0';    /* initialize global area */
  60.     memory->Dttl = 3600;
  61.     memory->Dclass = 1;
  62.  
  63.     /* This code can handle a few weird cases. It works when there's
  64.      * a PTR to a CNAME to the sought record, as well as when there's a
  65.      * CNAME to a PTR to the record. But it allows only one of each kind
  66.      * of indirection to prevent infinite loops.
  67.      */
  68.     while((rrp = dfind(dbase,name,type,memory)) == NULLRR){
  69.         /* No matching record was found, let's see if it's an alias */
  70.         if(cname == NULLCHAR
  71.           && (rrp = dfind(dbase,name,TYPE_CNAME,memory)) != NULLRR){
  72.             if((cname = strxdup(rrp->rdata.name)) == NULLCHAR)
  73.                 break;
  74.             name = cname;
  75.             rewind(dbase);
  76.             memory->Dname[0] = '\0'; /* initialize global area */
  77.             memory->Dttl = 3600;
  78.             memory->Dclass = 1;
  79.             memory->rrp = NULLRR;
  80.             xfree(memory->dorigin);
  81.             memory->dorigin = NULLCHAR;
  82.             free_rr(rrp);
  83.             continue;    /* Try again */
  84.         }
  85.         /* Lacking that, try a pointer entry... */
  86.         if(pname == NULLCHAR
  87.           && (rrp = dfind(dbase,name,TYPE_PTR,memory)) != NULLRR){
  88.             if((pname = strxdup(rrp->rdata.name)) == NULLCHAR)
  89.                 break;
  90.             name = pname;
  91.             rewind(dbase);
  92.             memory->Dname[0] = '\0';   /* initialize global area */
  93.             memory->Dttl = 3600;
  94.             memory->Dclass = 1;
  95.             memory->rrp = NULLRR;
  96.             xfree(memory->dorigin);
  97.             memory->dorigin = NULLCHAR;
  98.             free_rr(rrp);
  99.             continue;
  100.         }
  101.         /* Nope, nothing. Give up */
  102.         break;
  103.     }
  104.     fclose(dbase);
  105.     xfree(pname);
  106.     xfree(cname);
  107.     xfree(memory->dorigin);
  108.     xfree((char *)memory);
  109.     return rrp;
  110. }
  111.  
  112. #ifdef XXX
  113. /* Try to figure out if we are an authority; current strategy is:
  114.  * if a domain server is defined we do not have athority
  115.  */
  116. static int near
  117. haveaa(name)
  118. char *name;
  119. {
  120. return Dhaveaa;
  121.  
  122.     struct rr *rrp;
  123.     int len, cnt = 0;
  124.     char *cp = name;
  125.  
  126.     /* Try to find a SOA for the whole address and by stripping off
  127.        the first part of the address. */
  128.     while(cnt < 4 && (rrp = resolverec(cp,TYPE_SOA)) == NULLRR){
  129.         if((cp = strchr(cp,'.')) == NULLCHAR)
  130.             break;
  131.         if(*(++cp) == '\0')
  132.             break;
  133.         ++cnt;
  134.     }
  135.     if(rrp != NULLRR){
  136.         len = strxlen(rrp->rdata.soa->mname);
  137.         if(rrp->rdata.soa->mname[len-1] == '.')
  138.             --len;
  139.         if(len == strxlen(Hostname) &&
  140.            strncmp(Hostname,rrp->rdata.soa->mname,len) == 0){
  141.             free_rr(rrp);
  142.             return 1;
  143.         }
  144.         free_rr(rrp);
  145.     }
  146.     return 0;
  147. }
  148. #endif
  149.  
  150. /* Main entry point for domain name -> arbitrary record resolution.
  151.  * Returns a null pointer if name is definitely not valid.
  152.  */
  153. static struct rr * near
  154. rresolve(name,type,fflag)
  155. char *name;
  156. int type;
  157. int16 fflag;
  158. {
  159.     char *buf;
  160.     int i, len, recurse = 0, auth = 0, lcount = 0;
  161.     int16 flags;
  162.     struct rr *rrp = NULLRR, *rr, *rrtmp;
  163.     struct dhdr *dhdr;
  164.     struct mbuf *bp;
  165.     struct dserver *dp = Dlist;
  166.  
  167.     while((rrp = resolverec(name,type)) == NULLRR){
  168.         if(dp == NULLDOM)
  169.             break;
  170.  
  171.         if(auth == 0) {
  172.             if(Dhaveaa) {
  173. #ifdef XXX
  174.             if(haveaa(name)) {       /* Quit if we are an authority */
  175. #endif
  176.                 return NULLRR;
  177.             } else {
  178.                 auth = -1;
  179.             }
  180.         }
  181.         if(uploadstatus)
  182.             break;
  183.  
  184.         /* Not in file, send query */
  185.         flags = DOM_DORECURSE | fflag;        /* Recursion desired */
  186.         dhdr = bld_dhdr(QUERY,QUERY,flags,NO_ERROR,name,CLASS_IN,type);
  187.         buf = mxallocw(512);                /* buf is freed by sendquery */
  188.         len = res_mkbuf(dhdr,buf,512);
  189.         free_dhdr(dhdr);           /* actualy we need to keep the question for
  190.                                    later reference when an answer comes in */
  191.         dp->queries++;
  192.         if(sendquery(dp->address,buf,len,&bp,dp->timeout) > 0) {
  193.             dhdr = (struct dhdr *)mxallocw(sizeof(struct dhdr));
  194.             ntohdomain(dhdr,&bp);
  195.             dp->responses++;
  196.             proc_answer(dhdr,dp,NULLFILE);
  197.             if(dhdr->rcode != NO_ERROR) {
  198.                 break;
  199.             } else {
  200.                 for(i = 0; i < dhdr->ancount; i++){
  201.                     rrp = copy_rr(dhdr->ans[i]);
  202.                     if(strnicmp(rrp->name,name,strxlen(name)) != 0)
  203.                         continue;
  204.                     /* Got one */
  205.                     switch(rrp->type) {
  206.                     case TYPE_CNAME:
  207.                         /* Change the query name to the
  208.                          * cname and go back again
  209.                          */
  210.                         if(++recurse == MAXCNAME)
  211.                             /* too many recursions */
  212.                             break;
  213.  
  214.                         xfree(name);
  215.                         name = strxdup(rrp->rdata.name);
  216.                         /* rescan the responces */
  217.                         i = -1;
  218.                         continue;
  219.                     }
  220.                     break;
  221.                 }
  222.             }
  223.             free_dhdr(dhdr);
  224.             break;
  225.         }
  226.         if(errno == EABORT)
  227.             return NULLRR;
  228.  
  229.         /* Timeout; back off this one and try another server */
  230.         dp->timeout += 5000;
  231.         dp->missers++;
  232.         if((dp = dp->next) == NULLDOM)
  233.             break;
  234.         if(++lcount > Dretries)
  235.             return NULLRR;
  236.     }
  237.     rr = rrp;                         /* Remove any NULL records */
  238.     while(rr != NULLRR && rr->rdlength == 0){
  239.         rrp = rr->next;
  240.         rr->next = NULLRR;
  241.         free_rr(rr);
  242.         rr = rrp;
  243.     }
  244.     while(rr != NULLRR && rr->next != NULLRR){
  245.         if(rr->next->rdlength == 0){
  246.             rrtmp = rr->next->next;
  247.             rr->next->next = NULLRR;
  248.             free_rr(rr->next);
  249.             rr->next = rrtmp;
  250.         } else
  251.             rr = rr->next;
  252.     }
  253.     return rrp;
  254. }
  255.  
  256. /*----------------------------------------------------------------------*
  257. *retrieve the next useable entry in cache                               *
  258. *-----------------------------------------------------------------------*/
  259. static Cache * near
  260. getentry(void)
  261. {
  262. Cache *ocap, *cap = cache;
  263. int i;
  264. time_t ti;
  265.  
  266.    /*-------------------------------------------------------------------*
  267.    * scan cache for an useable entry. This might be a free entry..      *
  268.    * cap->ti == 0 or the oldest entry in Cache                          *
  269.    *--------------------------------------------------------------------*/
  270.    time(&ti);
  271.  
  272.    for (i = 0; i < Dcache_size; i++)   {
  273.       if (cap->ti == 0)
  274.          return(cap);
  275.       if (ti >= cap->ti)   {
  276.          ti = cap->ti;
  277.          ocap = cap;
  278.       }
  279.       cap++;
  280.    }
  281.    return(ocap);
  282. }
  283.  
  284. /*----------------------------------------------------------------------*
  285. * put an entry into the cache for later access                          *
  286. *-----------------------------------------------------------------------*/
  287. static Cache * near
  288. putcache(char *name,char *host,int32 addr,Rtype type,Ctype ctype)
  289. {
  290. Cache *cap = 0;
  291.    /*-------------------------------------------------------------------*
  292.    * Found it, put in cache                                             *
  293.    *--------------------------------------------------------------------*/
  294.    cap = getentry();
  295.    semwait(&Cwrite,1);                 /* -serialize Cache access      */
  296.    /*-------------------------------------------------------------------*
  297.    * make correct entries for valid and invalid entries                 *
  298.    *--------------------------------------------------------------------*/
  299.    if (type == Address && ctype == Found)  {          /* via resolve_a()*/
  300.       sprintf(cap->name,"%.39s",strtok(name,"\t "));
  301.    } else if (ctype == Found)         /* found in file                */
  302.       sprintf(cap->name,"%.39s",host);
  303.  
  304.    if (type == Name && ctype == Missing)  {
  305.       cap->address = 0;
  306.       sprintf(cap->name,"%.39s",host);
  307.    } else
  308.       cap->address = (ctype != Found) ? 0 : addr;
  309.  
  310.    cap->type = ctype;
  311.    cap->ti = time(NULL);
  312.    semrel(&Cwrite);
  313.    return cap;
  314. }
  315.  
  316. /*----------------------------------------------------------------------*
  317. *  Perform a cache search.
  318. *-----------------------------------------------------------------------*/
  319. static Cache * near
  320. cache_search(char *name,Rtype type)
  321. {
  322. int i;
  323. char *cp;
  324. Cache *cap = cache;
  325.  
  326.    for (i = 0; i < Dcache_size; i++) {
  327.       if(i == Dcache_size)
  328.          break;
  329.       if(cap->ti == 0)
  330.          continue;
  331.       if (type == Name)   {
  332.          if(cap->name[0] != '\0') {
  333.             if(strchr(name,'.') == NULLCHAR) {
  334.                 if((cp = strchr(cap->name,'.')) != NULLCHAR)
  335.                     *cp = '\0';
  336.                 if(stricmp(cap->name,name) == 0) {
  337.                     *cp = '.';
  338.                     return cap;
  339.                 }
  340.                 *cp = '.';
  341.             } else if(strnicmp(cap->name,name,(strxlen(name) - 1)) == 0)
  342.                 return cap;
  343.          }
  344.       } else {
  345.          if(cap->address != 0 && cap->address == aton(name))   {
  346.             return cap;
  347.          }
  348.       }
  349.       cap++;
  350.    }
  351.    return(0);
  352. }
  353.  
  354. /* Main entry point for domain name -> address resolution.
  355.  * Returns 0 if name is definitely not valid.
  356.  */
  357. int32
  358. resolve(name)
  359. char *name;
  360. {
  361.     char *sname;
  362.     int state = Found;
  363.     int32 addr = 0;
  364.     struct rr *arrp = NULLRR;
  365.     Cache *cap;
  366.  
  367.     if(*name == '[')
  368.         return aton(name + 1);
  369.  
  370.     if(isaddr(name))
  371.         return aton(name);
  372.  
  373.     if((cap = cache_search(name,Name)) != 0)
  374.         return (cap->type == Found) ? cap->address : 0;
  375.  
  376.     sname = strxdup(name);
  377.  
  378.     if((arrp = rresolve(sname,TYPE_A,DOM_CANRECURSE)) != NULLRR
  379.       && arrp->rdlength == 4) {
  380.         addr = arrp->rdata.addr;
  381.         xfree(sname);
  382.         sname = strxdup(arrp->name);
  383.     }
  384.     if(addr == 0)
  385.         state = Missing;
  386.  
  387.     if(cap == 0)
  388.         putcache(NULLCHAR,sname,addr,Name,state);
  389.     xfree(sname);
  390.     free_rr(arrp);
  391.     return addr;
  392. }
  393.  
  394. /* entry point for address -> domain name resolution.
  395.  * Returns NULLCHAR if address is not found.
  396.  */
  397. char *
  398. resolve_a(ip_address,shorten)
  399. int32 ip_address;
  400. int shorten;
  401. {
  402.     static char pname[130];
  403.     Cache *cap;
  404.  
  405.     if(ip_address == 0L)
  406.         return NULLCHAR;
  407.  
  408.     sprintf(pname,"%u.%u.%u.%u",
  409.         hibyte(hiword(ip_address)),
  410.         lobyte(hiword(ip_address)),
  411.         hibyte(loword(ip_address)),
  412.         lobyte(loword(ip_address)));
  413.  
  414.     if((cap = cache_search(pname,Address)) != 0 && cap->type == Found) {
  415.         int i = strxlen(cap->name) - 1;
  416.         if (cap->name[i] != '.') {
  417.             if (shorten) {
  418.                 return cap->name;
  419.             } else if (Dsuffix) {
  420.                 sprintf(pname,"%s.%s",cap->name,Dsuffix);
  421.                 pname[strxlen(pname) - 1] = '\0';
  422.                 return pname;
  423.             }
  424.         } else {
  425.             strcpy(pname, cap->name);
  426.             if (shorten) {
  427.                 if (Dsuffix) {
  428.                     char *j = strstr(pname, Dsuffix);
  429.                     if (j > pname && *(--j) == '.')
  430.                         *j = '\0';
  431.                     else
  432.                         pname[strxlen(pname)-1] = '\0';
  433.                     return pname;
  434.                 }
  435.             } else {
  436.                 pname[i] = '\0';
  437.                 return pname;
  438.             }
  439.         }
  440.     }
  441.     return NULLCHAR;
  442.  
  443. #ifdef notdef
  444.  
  445.     struct rr *rrp, *irrp, *prrp;
  446.  
  447.     sprintf( pname, "%u.%u.%u.%u%s",
  448.             lobyte(loword(ip_address)),
  449.             hibyte(loword(ip_address)),
  450.             lobyte(hiword(ip_address)),
  451.             hibyte(hiword(ip_address)),
  452.             shorten ? "" : ".IN-ADDR.ARPA." );
  453.  
  454.     irrp = make_rr(RR_INQUERY,NULLCHAR,CLASS_IN,TYPE_A,0,4,&ip_address);
  455.     prrp = make_rr(RR_QUERY,pname,CLASS_IN,TYPE_PTR,0,0,NULL);
  456.  
  457.     irrp->next = prrp;    /* make list to speed search */
  458.  
  459.     for(dname = NULLCHAR; dname == NULLCHAR;){
  460.         if((rrp=dcache_search(irrp)) == NULLRR
  461.         && (rrp=dfile_search(irrp)) == NULLRR
  462.         && (rrp=dns_query(prrp,1)) == NULLRR)
  463.             break;
  464.         if(rrp->rdlength == 0)
  465.             break;
  466.         switch(rrp->type){
  467.         case TYPE_A:
  468.             dname = strxdup(rrp->name);
  469.             break;
  470.         case TYPE_PTR:
  471.             dname = strxdup(rrp->rdata.name);
  472.             break;
  473.         default:
  474.             free_rr(rrp);
  475.         }
  476.     }
  477.     free_rr(irrp);
  478.     free_rr(prrp);
  479.     free_rr(rrp);
  480.     return dname;
  481. #endif
  482. }
  483.  
  484. /* Main entry point for MX record lookup.
  485.  * Returns NULLCHAR if name is currently unresolvable.
  486.  */
  487. char *
  488. resolve_mailb(name)
  489. char *name;
  490. {
  491.     struct rr *rrp, *arrp;
  492.     char *sname, *tmp, *cp;
  493.     int32 addr = 0;
  494.     int16 pref = MAXINT16;
  495.  
  496.     if(name == NULLCHAR)
  497.         return NULLCHAR;
  498.  
  499.     if(isaddr(name)) {
  500.         if((sname = resolve_a(aton(name),FALSE)) == NULLCHAR)
  501.             return NULLCHAR;
  502.     } else {
  503.         sname = mxallocw(strxlen(name) + 2);
  504.         sprintf(sname,"%s.",name);
  505.     }
  506.     cp = sname;
  507.  
  508.     while(1){
  509.         rrp = arrp = rresolve(sname,TYPE_MX,DOM_CANRECURSE);
  510.         rrp = NULLRR;
  511.         /* Search this list of rr's for an MX record */
  512.         while(rrp != NULLRR){
  513.             if(rrp->rdlength > 0 && rrp->rdata.mx.pref <= pref
  514.               && (addr = resolve(rrp->rdata.mx.exch)) != 0L) {
  515.                 pref = rrp->rdata.mx.pref;
  516.             }
  517.             rrp = rrp->next;
  518.         }
  519.         free_rr(arrp);
  520.         if(addr != 0)
  521.             break;
  522.         /* Compose wild card one level up */
  523.         if((cp = strchr(cp,'.')) == NULLCHAR)
  524.             break;
  525.         tmp = mxallocw(strxlen(cp)+2);
  526.         sprintf(tmp,"*%s",cp);        /* wildcard expansion */
  527.         xfree(sname);
  528.         sname = tmp;
  529.         cp = sname + 2;
  530.     }
  531.  
  532.     if(Dsuffix != NULLCHAR && addr != 0) {
  533.         tmp = mxallocw(strxlen(sname) + strxlen(Dsuffix) + 2);
  534.         sprintf(tmp,"%s.%s",sname,Dsuffix);
  535.         xfree(sname);
  536.         return tmp;
  537.     }
  538.     xfree(sname);
  539.     return NULLCHAR;
  540. }
  541.  
  542. #ifdef XXX
  543. /* process outgoing zoneinit */
  544. static void
  545. proc_bootp(s,d,b)
  546. int s;
  547. void *d;
  548. void *b;
  549. {
  550.     int i, count, len, auth, answers = 5;
  551.     char *buf, *name;
  552.     struct sockaddr_in server;
  553.     struct rr *rrp;
  554.     struct quest *qp;
  555.     struct rr_memory *memory;
  556.     FILE *fp;
  557.     struct mbuf *bp;
  558.     struct dserver *dp = (struct dserver *) d;
  559.     struct dhdr *dhdr = (struct dhdr *) b;
  560.  
  561.     if(dhdr->qdcount != 1) {
  562.         free_dhdr(dhdr);
  563.         xfree((char *)dp);
  564.         return;
  565.     }
  566.     qp = dhdr->qlist[0];                     /* expecting only 1 question */
  567.  
  568.     if(qp->qtype ==  TYPE_ANY) {
  569.         auth = DOM_AUTHORITY | DOM_CANRECURSE;
  570.         name = strxdup(qp->qname);
  571.         i = strxlen(name);
  572.         if(name[--i] == '.')
  573.             name[i] = '\0';                 /* undo effect of dn_compress */
  574.         dhdr->rcode = NO_ERROR;
  575.         dhdr->aa = auth;
  576.         dhdr->qr = RESPONSE;
  577.         dhdr->opcode = QUERY;                 /* change opcode for answers */
  578.         if((fp = fopen(name,READ_TEXT)) == NULLFILE) {
  579.             xfree(name);
  580.             free_dhdr(dhdr);
  581.             xfree((char *)dp);
  582.             return;
  583.         }
  584.         memory = (struct rr_memory *)mxallocw(sizeof(struct rr_memory));
  585.         dhdr->ans = (struct rr **)cxallocw(answers,sizeof(struct rr *));
  586.         server.sin_family = AF_INET;
  587.         server.sin_port = dp->port;
  588.         server.sin_addr.s_addr = dp->address;
  589.         count = 0;
  590.         buf = mxallocw(512);
  591.         while((rrp = get_rr(fp,memory)) != NULLRR) {
  592.             dhdr->ans[count++] = rrp;
  593.             if(count == answers) {
  594.                 dhdr->ancount = answers;
  595.                 len = res_mkbuf(dhdr,buf,512);
  596.                 bp = qdata(buf,(int16)len);
  597.                 send_mbuf(s,bp,0,(char *)&server,sizeof(server));
  598.                 for(i = 0; i < answers; i++) {
  599.                     free_rr(dhdr->ans[i]);
  600.                     dhdr->ans[i] = NULLRR;
  601.                 }
  602.                 count = 0;
  603.                 alarm(Dtimeout * 1000);
  604.                 /* Wait for something to happen */
  605.                 pwait(&s);
  606.                 alarm(0L);
  607.             }
  608.         }
  609.  
  610.         dhdr->ancount = count;
  611.         len = res_mkbuf(dhdr,buf,512);
  612.         free_dhdr(dhdr);
  613.         bp = qdata(buf,(int16)len);
  614.         send_mbuf(s,bp,0,(char *)&server,sizeof(server));
  615.         xfree(buf);
  616.         xfree((char *)dp);
  617.         xfree(name);
  618.         fclose(fp);
  619.     }
  620. }
  621. #endif
  622.  
  623. /* process incoming queries */
  624. void
  625. proc_query(s,d,b)
  626. int s;
  627. void *d;
  628. void *b;
  629. {
  630.     int i, len, auth;
  631.     char *buf;
  632.     struct sockaddr_in server;
  633.     struct rr *rrp, *rrans, *rrns, *rradd, *rrtmp;
  634.     struct quest *qp;
  635.     struct mbuf *bp;
  636.  
  637.     struct dserver *dp = (struct dserver *) d;
  638.     struct dhdr *dhdr = (struct dhdr *) b;
  639.     rrans = rrns = rradd = NULLRR;
  640.  
  641.     for(i = 0; i < dhdr->qdcount; i++) {
  642.         qp = dhdr->qlist[i];
  643.         /* A server is testing here. ASSUMING INTERNET STYLE */
  644.         auth = (Dhaveaa) ? (DOM_AUTHORITY | DOM_CANRECURSE) : DOM_CANRECURSE;
  645. #ifdef XXX
  646.         auth = (haveaa(qp->qname)) ? (DOM_AUTHORITY | DOM_CANRECURSE) : DOM_CANRECURSE;
  647. #endif
  648.         switch(qp->qtype) {
  649.         case TYPE_A:
  650.             if((rrp = rresolve(qp->qname,TYPE_A,DOM_CANRECURSE)) != NULLRR) {
  651.                 /* we found an entry, go tell him */
  652.                 dhdr->rcode = NO_ERROR;
  653.                 dhdr->aa = auth;
  654.                 dhdr->qr = RESPONSE;
  655.                 rrans = rrp;
  656.             } else {
  657.                 /* we did not find an entry, go tell him */
  658.                 rrp = (struct rr *)mxallocw(sizeof(struct rr));
  659.                 rrp->name = strxdup(qp->qname);
  660.                 rrp->type = qp->qtype;
  661.                 rrp->class = qp->qclass;
  662.                 rrp->ttl = 500L;
  663.                 rrp->rdata.addr = 0L;
  664.                 rrp->rdlength = 4;    /* size of addr data */
  665.                 dhdr->rcode = NAME_ERROR;
  666.                 dhdr->aa = auth;
  667.                 dhdr->qr = RESPONSE;
  668.                 rrans = rrp;
  669.             }
  670.             break;
  671.         case TYPE_MB:
  672.         case TYPE_MG:
  673.         case TYPE_MR:
  674.         case TYPE_MX:
  675.         case TYPE_NS:
  676.         case TYPE_SOA:
  677.         case TYPE_PTR:
  678.         case TYPE_TXT:
  679.         case TYPE_CNAME:
  680.         case TYPE_HINFO:
  681.         case TYPE_ANY:
  682.             if((rrp = rresolve(qp->qname,qp->qtype,DOM_CANRECURSE)) != NULLRR){
  683.                 dhdr->rcode = NO_ERROR;
  684.                 dhdr->aa = auth;
  685.                 dhdr->qr = RESPONSE;
  686.             } else {
  687.                 dhdr->rcode = NAME_ERROR;
  688.                 dhdr->aa = auth;
  689.                 dhdr->qr = RESPONSE;
  690.             }
  691.             rrans = rrp;
  692.             break;
  693.         /* if I cannot give a reasonable answer , dont give it ... */
  694.         case TYPE_MD:        /* unsupported */
  695.         case TYPE_MF:        /* unsupported */
  696.         case TYPE_WKS:        /* unsupported */
  697.         case TYPE_NULL:        /* unsupported */
  698.         case TYPE_MINFO:    /* unsupported */
  699.         default:
  700.             dhdr->rcode = NOT_IMPL;
  701.             dhdr->aa = auth;
  702.             dhdr->qr = RESPONSE;
  703.         }
  704.     }
  705.     i = 0;
  706.     rrtmp = rrans;
  707.     while(rrtmp != NULLRR) {
  708.         i++;
  709.         rrtmp = rrtmp->next;
  710.     }
  711.     dhdr->ancount = i;
  712.     if(i > 0) {
  713.         dhdr->ans = (struct rr **)cxallocw(i,sizeof(struct rr *));
  714.         rrtmp = rrans;
  715.         i = 0;
  716.         while(rrtmp != NULLRR) {
  717.         dhdr->ans[i] = rrtmp;
  718.             i++;
  719.             rrans = rrtmp;
  720.             rrtmp = rrtmp->next;
  721.             rrans->next = NULLRR; /* break link */
  722.         }
  723.     }
  724.     i = 0;
  725.     rrtmp = rrns;
  726.     while(rrtmp != NULLRR) {
  727.         i++;
  728.         rrtmp = rrtmp->next;
  729.     }
  730.     dhdr->nscount = i;
  731.     if(i > 0) {
  732.         dhdr->ns = (struct rr **)cxallocw(i,sizeof(struct rr *));
  733.         rrtmp = rrns;
  734.         i = 0;
  735.         while(rrtmp != NULLRR) {
  736.         dhdr->ns[i] = rrtmp;
  737.             i++;
  738.             rrns = rrtmp;
  739.             rrtmp = rrtmp->next;
  740.             rrns->next = NULLRR; /* break link */
  741.         }
  742.     }
  743.     i = 0;
  744.     rrtmp = rradd;
  745.     while(rrtmp != NULLRR) {
  746.         i++;
  747.         rrtmp = rrtmp->next;
  748.     }
  749.     dhdr->arcount = i;
  750.     if(i > 0) {
  751.         dhdr->add = (struct rr **)cxallocw(i,sizeof(struct rr *));
  752.         rrtmp = rradd;
  753.         i = 0;
  754.         while(rrtmp != NULLRR) {
  755.         dhdr->add[i] = rrtmp;
  756.             i++;
  757.             rradd = rrtmp;
  758.             rrtmp = rrtmp->next;
  759.             rradd->next = NULLRR; /* break link */
  760.         }
  761.     }
  762.     buf = mxallocw(512);
  763.     len = res_mkbuf(dhdr,buf,512);
  764.     free_dhdr(dhdr);
  765.     server.sin_family = AF_INET;
  766.     server.sin_port = dp->port;
  767.     server.sin_addr.s_addr = dp->address;
  768.     bp = qdata(buf,(int16)len);
  769.     send_mbuf(s,bp,0,(char *)&server,sizeof(server));
  770.     xfree(buf);
  771.     xfree((char *)dp);
  772. }
  773. /* ----------------------- Domain server start/stop ----------------------- */
  774.  
  775. int
  776. dom1(int argc,char *argv[],void *p)
  777. {
  778.     struct sockaddr_in lsocket,from;
  779.     int fromlen;
  780.     struct mbuf *bp;
  781.     struct dhdr *dhdr;
  782.     struct dserver *dp;
  783.  
  784.     if(SDom != -1)
  785.         return 0;
  786.     psignal(Curproc,0);
  787.     chname(Curproc,"Domain listener");
  788.     lsocket.sin_family = AF_INET;
  789.     lsocket.sin_addr.s_addr = INADDR_ANY;
  790.     lsocket.sin_port = (argc < 2) ? IPPORT_DOMAIN : atoi(argv[1]);
  791.  
  792.     SDom = socket(AF_INET,SOCK_DGRAM,0);
  793.     bind(SDom,(char *)&lsocket,sizeof(lsocket));
  794.     for(;;){
  795.         fromlen = sizeof(from);
  796.         if(recv_mbuf(SDom,&bp,0,(char *)&from,&fromlen) == -1)
  797.             break;
  798.         dhdr = (struct dhdr *)mxallocw(sizeof(struct dhdr));
  799.             if (ntohdomain(dhdr,&bp) == -1)
  800.                   continue;        /* something wrong with this packet */
  801.                  if(dhdr->qr != RESPONSE) {
  802.             dp = (struct dserver *)mxallocw(sizeof(struct dserver));
  803.             dp->address = from.sin_addr.s_addr;
  804.             dp->port = from.sin_port;
  805.             if(dhdr->opcode != ZONEINIT)
  806.                 newproc("Domain query",1024,proc_query,SDom,(void *)dp,(void *)dhdr,0);
  807.         }
  808.     }
  809.     return 0;
  810. }
  811.  
  812. int
  813. dom0(int argc,char *argv[],void *p)
  814. {
  815.     close_s(SDom);
  816.     SDom = -1;
  817.     return 0;
  818. }
  819.  
  820.  
  821.